package item69;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;

/**
 * 第69条：并发工具优先于wait和notify
 */
public class Main01 {


    private static final ConcurrentMap<String, String> map = new ConcurrentHashMap<>();

    // Concurrent canonicalizing map atop ConcurrentMap - not optimal
    // 并发map顶部的并发规范映射 - 不是最优的
    public static String intern(String s) {
        String previousValue = map.putIfAbsent(s, s);
        return previousValue == null ? s : previousValue;
    }

    // Concurrent canonicalizing map atop ConcurrentMap - faster!
    // 并发map顶部的并发规范映射 - 更快
    public static String intern2(String s) {
        String result = map.get(s);
        if (result == null) {
            result = map.putIfAbsent(s, s);
            if (result == null)
                result = s;
        }
        return result;
    }

    public static long time(Executor executor, int concurrency, final Runnable action) throws InterruptedException {
        final CountDownLatch ready = new CountDownLatch(concurrency);
        final CountDownLatch start = new CountDownLatch(1);
        final CountDownLatch done = new CountDownLatch(concurrency);
        for (int i = 0; i < concurrency; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    ready.countDown(); // Tell timer we're ready
                    try {
                        start.await(); // Wait till peers are ready
                        action.run();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    } finally {
                        done.countDown(); // tell timer we're done
                    }


                }
            });
        }
        ready.await(); // wait for all workers to be ready
        long startNanos = System.nanoTime();
        start.countDown(); // And they're off!
        done.await(); // wait for all workers to finish
        return System.nanoTime() - startNanos;
    }

    public static void main(String[] args) {
        // 既然正确地使用wait和notify比较困难，就应该用更高级的并发工具来代替。

        // 更高级的并发工具为  Executor Framework、并发集合(Concurrent collection)以及同步器(synchronizer)

        // 并发集合中不可能排除并发活动;将它锁定没有什么作用，只会使程序的速度变慢。

        System.out.println(intern("中国"));

        System.out.println(intern2("中国人"));

        // 除非不得已，否则应该优先使用ConcurrentHashMap,而不是使用Collections.synchronizedMap或者Hashtable.

        // 同步器是一些使线程能够等待另一个线程的对象，允许它们协调动作。

        // 对于间歇式的定时，始终应该优先使用System.nanoTime,而不是使用System.currentTimeMills.

        // 始终应该使用wait循环模式来调用wait方法;永远不要在循环之外调用wait方法。

        // 没有理由在新代码中使用wait和notify,即使有，也是极少的。
    }

}
